package myJs.user.predict

import com.softwaremill.quicklens._
import myJs.Utils._
import myJs.api.Api
import myJs.cps.{FormGroupInlineCp, NumInputCp, PureInputCp, Style}
import myJs.myPkg.jquery.{$, JQueryAnimationSettings}
import myJs.myPkg.reactHookForm._
import myJs.myPkg.{SwalOptions, layer, swal}
import myJs.tool.Tool
import myJs.user.home.Cp.curPage
import myJs.CpLayer
import myJs.myPkg.d3v4.d3
import org.scalajs.macrotaskexecutor.MacrotaskExecutor.Implicits._
import shared.pojo.Pojo.predict._
import slinky.core.FunctionalComponent
import slinky.core.annotations.react
import slinky.core.facade.Hooks._
import slinky.web.html._
import typings.csstype.csstypeStrings

import scala.scalajs.js
import scala.scalajs.js.Dynamic.{global => g}
import scala.scalajs.js.JSON

/** Created by yz on 21/1/2022
  */
@react object PredictResultCp {

  case class Props(
      missionId: Int
  )

  val component = FunctionalComponent[Props] { props =>
    val useForm = ReactHookForm.useForm(UseFormOptions(mode = "onChange"))
    val (resultRow, setResultRow) = useState(PredictResult.Response())
    val (show, setShow) = useState(false)
    val (myToolShow, setMyToolShow) = useState(false)
    val (time, setTime) = useState("")
    object FTool {

      def refreshResult = {
        val index = layer.load(1, layerOptions.copy(shade = List("0.1", "#fff")))
        val request = PredictResult.Request(missionId = props.missionId, userId = Tool.getUserId)
        Api.predict.predictResult(request).map { response =>
          layer.close(index)
          setResultRow(response)
          setShow(true)
        }
        ()
      }

      def myToolShowChange = (v: Boolean) => {
        setMyToolShow(v)
      }

      def refreshSvg(score: BigDecimal, scale: Double, svgId: String) = {
        $(s"#${svgId}").empty()
        val width = 750 * scale
        val height = 160 * scale

        val totalWidth = 720
        val markerWidth = 10
        val scoreWidth = score * totalWidth - markerWidth
        val lw = "0.5"
        val colors = js.Array("#03FF00", "#D6FF00", "#FFEC00", "#FF9B00", "#FF1A00", "#C20000")
        val offsets = js.Array(0, 0.3, 0.4, 0.6, 0.85, 1)
        val tickts = offsets.drop(1).dropRight(1)
        val svg = d3
          .select(s"#${svgId}")
          .append("svg")
          .attr("width", width)
          .attr("height", height)
          .attr("xmlns", "http://www.w3.org/2000/svg")
          .attr("xmlns:xlink", "http://www.w3.org/1999/xlink")
        val lengendSvg =
          svg.append("g").attr("transform", s"translate(10,30)scale(${scale},${scale})")
        val defs = svg.append("defs")
        defs
          .append("linearGradient")
          .attr("id", "colors")
          .attr("x1", "0%")
          .attr("y1", "0%")
          .attr("x2", "100%")
          .attr("y2", "0%")
          .selectAll("stop")
          .data(colors)
          .enter()
          .append("stop")
          .attr("offset", (d: String, i: Int) => offsets(i))
          .attr("stop-color", (d: String) => d)
          .attr("stop-opacity", 1)

        defs
          .append("marker")
          .attr("id", "arrow")
          .attr("markerHeight", 4)
          .attr("refy", 0)
          .attr("orient", "auto")
          .attr("viewBox", "0 -5 10 10")
          .append("path")
          .attr("d", "M0,-3L3,0L0,3")
          .style("fill", "#002060")

        lengendSvg
          .append("rect")
          .attr("x", 0)
          .attr("width", totalWidth)
          .attr("height", 50)
          .style("fill", "url(#colors)")

        val xScale = d3.scaleLinear().range(js.Array(0, totalWidth)).domain(js.Array(0, 1))
        val xAxis = d3
          .axisBottom(xScale)
          .tickValues(js.Array(0, 0.25, 0.5, 0.75, 1).asInstanceOf[js.Array[js.Any]])
          .tickFormat((v: js.Object) => {
            v.toString
          })
        val xAxisSvg = lengendSvg
          .append("g")
          .attr("class", "axis")
          .attr("transform", s"translate(0,100)")
          .call(xAxis)

        xAxisSvg
          .select(".axis .domain")
          .attr("d", "M0,0V0H720V0")
          .style("fill", "none")
          .style("stroke", "#BACBE9")
          .style("stroke-width", "2px")
          .style("shape-rendering", "crispEdges")
        xAxisSvg
          .selectAll(".axis line")
          .attr("y2", "-50")
          .style("stroke", "#000000")
          .style("stroke-width", 5)
          .attr("x2", "0")
          .attr("y1", "0")
          .attr("stroke-dasharray", "10,30")
        xAxisSvg.select(".axis line").attr("x1", "2").attr("x2", "2")
        xAxisSvg
          .selectAll(".axis line")
          .filter { (d: js.Any, i: Int) =>
            i == 4
          }
          .attr("x1", "-3")
          .attr("x2", "-3")

        lengendSvg
          .append("line")
          .attr("x1", 0)
          .attr("y1", 75)
          .attr("x2", scoreWidth.toDouble)
          .attr("y2", 75)
          .style("stroke", "#002060")
          .style("stroke-width", 9)
          .style("marker-end", "url(#arrow)")
      }

      def exportShow = () => {
        Api.tool.getServerTime.map { response =>
          setTime(response)
          setMyToolShow(true)
        }
        ()
      }

    }

    useEffect(
      () => {
        FTool.refreshResult
      },
      List()
    )

    useEffect(
      () => {
        if (resultRow.mission.score.nonEmpty) {
          val score = BigDecimal(resultRow.mission.score)
          FTool.refreshSvg(score, 1, "svg")
          FTool.refreshSvg(score, 2, "svg1")
        }
      },
      List(resultRow)
    )

    useEffect(
      () => {
        if (show) {
          val target_top = $("#result").offset().top
          $("html,body").animate(
            js.Dictionary("scrollTop" -> target_top),
            JQueryAnimationSettings(duration = 800)
          )
        }
      },
      List(show)
    )

    val displayStr = if (show) csstypeStrings.block else csstypeStrings.none
    div(
      id := "result",
      style := Style(display = displayStr),
      div(
        className := "row",
        div(
          className := "col-md-12 col-sm-12",
          div(
            className := "portlet green-jungle box",
            div(
              className := "portlet-title",
              div(className := "caption", "预测结果"),
              div(
                className := "actions",
                div(
                  className := "btn-group",
                  a(
                    onClick := FTool.exportShow,
                    className := "btn green btn-outline btn-circle btn-sm",
                    data - "close-others" := "true",
                    i(className := "fa fa-pencil", " 导出Pdf报告")
                  )
                )
              )
            ),
            div(
              className := "portlet-body",
              div(
                className := "tab-pane active",
                h3(
                  div(s"样本号: ${resultRow.extra.sampleId}")
                ),
                h3(
                  div(s"姓名: ${resultRow.extra.name}")
                ),
                div(style := Style(marginLeft = 30, marginBottom = 30), id := "svg"),
                div(
                  style := Style(marginLeft = 30, marginBottom = 30, display = csstypeStrings.none),
                  id := "svg1"
                ),
                div(
                  className := "table-responsive",
                  style := Style(width = "60%"),
                  table(
                    className := "display table table-bordered",
                    thead(
                      tr(
                        th("受检者肝纤维化程度、肝硬化风险评分"),
                        th("健康情况预测结果"),
                        th("说明")
                      )
                    ),
                    tbody(
                      tr(
                        td("[0, 0.25]"),
                        td("低慢性肝病风险"),
                        td("肝脏代谢指标综合分析良好，提示比较健康，肝纤维化、肝硬化的可能性比较低。")
                      ),
                      tr(
                        td("(0.25, 0.5]"),
                        td("早期肝纤维化风险"),
                        td("肝脏代谢指标综合分析出现轻微异常，提示早期肝纤维化的可能性非常大。")
                      ),
                      tr(
                        td("(0.5, 0.75]"),
                        td("晚期肝纤维化风险"),
                        td("肝脏代谢指标综合分析出现严重异常，提示晚期肝纤维化的可能性非常大。")
                      ),
                      tr(
                        td("(0.75, 1]"),
                        td("肝硬化风险"),
                        td("肝脏代谢指标综合分析出现警示，提示肝硬化的可能性非常大。")
                      )
                    )
                  )
                ),
                pre(
                  id := "suggestion1",
                  s"计算得到的得分值为：${resultRow.mission.score},具有${resultRow.mission.result}。"
                )
              )
            )
          )
        )
      ),
      MyToolCp(row = resultRow, show = myToolShow, showChange = FTool.myToolShowChange, time = time)
    )
  }

}
